#include "media_diagnosis.h"

#include <algorithm>
#include <future>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <fstream>
#include <vector>
#include <cstdint>

#include "utils_file_ex.h"
#include "utils_string_ex.h"
#include "utils_log.h"
#include "common_shell.h"
#include "media_speak.h"

namespace El {
namespace Media {

CStreamDiagnosis &CStreamDiagnosis::GetInstance()
{
    static CStreamDiagnosis cLVLive;
    return cLVLive;
}

bool CStreamDiagnosis::Start()
{
    Common::Shell::GetInstance().RegisterCommand("stream",
                                                 std::bind(&CStreamDiagnosis::Record, this, std::placeholders::_1));

    Common::Shell::GetInstance().RegisterCommand("speak",
                                                 std::bind(&CStreamDiagnosis::Speak, this, std::placeholders::_1));
    return true;
}

void CStreamDiagnosis::Record(const std::string &args)
{
    EL_INFO("Record {}", args.c_str());

    // 解析args字段，获取参数，分别是：channel、stream_type、start
    std::vector<std::string> vecArgs;
    Utils::Split(args, " ", vecArgs);
    if (vecArgs.size() < 3) {
        EL_ERROR("Invalid args: {}", args.c_str());
        return;
    }
    int32_t ch = std::stoi(vecArgs[0]);
    int32_t streamType = std::stoi(vecArgs[1]);
    if (vecArgs[2] == "start") {
        stream_ = Media::StreamSource::Create(ch, streamType);
        stream_->SetInfo(120, "stream diagnosis");
        handle_ = stream_->Register(std::bind(&CStreamDiagnosis::OnStream, this, std::placeholders::_1));
        stream_->Start();
    } else if (vecArgs[2] == "stop") {
        stream_->Stop();
        stream_.reset();
    } else {
        EL_ERROR("Invalid command: {}", vecArgs[2].c_str());
    }
}

void CStreamDiagnosis::OnStream(const MediaFramePtr &ptr)
{
    EL_INFO("OnStream: {}", ptr->ToString().c_str());
    std::vector<uint8_t> content(ptr->GetBuffer(), ptr->GetBuffer() + ptr->GetLength());
    if (ptr->IsVideoFrame()) {
        Utils::SaveBufferToFile("/mnt/udisk/record.h264", content, false);
    } else if (ptr->IsAudioFrame()) {
        Utils::SaveBufferToFile("/mnt/udisk/record.g711a", content, false);
    }
}

void CStreamDiagnosis::Speak(const std::string &args)
{
    EL_INFO("Speak {}", args.c_str());

    // 解析args字段，获取参数，分别是：channel、stream_type、start
    std::vector<std::string> vecArgs;
    Utils::Split(args, " ", vecArgs);
    if (vecArgs.size() < 1) {
        EL_ERROR("Invalid args: {}", args.c_str());
        return;
    }

    if (vecArgs[0] == "mp3") {
        std::string path = "/mnt/data/speak.mp3";
        Media::Speak::GetInstance().StartFilePlay(path.c_str(), 1);
    } else if (vecArgs[0] == "opus") {
        std::string path = "/mnt/data/opus.opus";
        HAL_ADEC_COM_CONFIG_S adecConfig;
        memset(&adecConfig, 0, sizeof(HAL_ADEC_COM_CONFIG_S));
        adecConfig.eType = HAL_AUDIO_TYPE_OPUS;
        adecConfig.u32SampleRate = HAL_AUDIO_SAMPLE_RATE_48000;
        adecConfig.u8ChanNum = 1;
        adecConfig.u8Vol = 6;
        Media::Speak::GetInstance().StartFilePlay(path.c_str(), 1, &adecConfig);
    } else if (vecArgs[0] == "stop") {
        Media::Speak::GetInstance().Stop();
    } else {
        EL_ERROR("Invalid command: {}", vecArgs[0].c_str());
    }
}

} // namespace Media
} // namespace El